package two

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

// 为handler接口增加Router
type Handler interface {
	// http.Handler // 需要ServeHTTP方法
	ServeHTTP(c *Context)
	Routerable
}

type Routerable interface {
	Route(method string, pattern string, handlerfunc func(c *Context))
}

// 依据map结构的路由
type handlerBaseOnMap struct {
	handlers map[string]func(c *Context)
}

func (h *handlerBaseOnMap) Key(method, pattern string) string {
	// return fmt.Sprintf("%s#%s", method, pattern)
	return method + "#" + pattern
}

// func (h *handlerBaseOnMap) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func (h *handlerBaseOnMap) ServeHTTP(c *Context) {
	// 查找得到，即成功映射；查找不到，则404
	// k := h.Key(r.Method, r.URL.Path)
	k := h.Key(c.R.Method, c.R.URL.Path)
	if handler, ok := h.handlers[k]; ok {
		// handler(NewContext(w, r))
		handler(NewContext(c.W, c.R))
	} else {
		c.W.WriteHeader(http.StatusNotFound)
		c.W.Write([]byte("no found ,404"))
	}
}

func (h *handlerBaseOnMap) Route(method string, pattern string, handlerfunc func(c *Context)) {
	k := h.Key(method, pattern)
	h.handlers[k] = handlerfunc
}

// 构建Map路由
func NewHandlerBaseOnMap() Handler { //返回接口
	return &handlerBaseOnMap{
		handlers: make(map[string]func(c *Context)),
	}
}

var _ Handler = &handlerBaseOnMap{}

// 中间件数据结构
type FilterBuilder func(next Filter) Filter
type Filter func(c *Context)

// 相关中间件

// 打印请求时间的中间件
func MetricFilterBuilder(next Filter) Filter {
	return func(c *Context) {
		startTime := time.Now().UnixNano()
		next(c)
		endTime := time.Now().UnixNano()
		fmt.Printf("run time %d", endTime-startTime)
	}
}

// ============================================================================

// func main() {
// 	http.HandleFunc("/hello", Hello)
// 	// http.HandleFunc("/SignUp", SignUp)
// 	s := NewSignServer("web1")
// 	s.Route("/SignUp", SignUp)
// 	s.Start(":8089")
// }

func Hello(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello Go Web"))
}

type signUpReq struct {
	Email             string `json:"email"`
	Password          string `json:"password"`
	ConfirmedPassword string `json:"con"`
}

// -----------------------------增加Server-------------------------------
type Server interface {
	Routerable //路由
	Start(address string) error
}

type HttpServer struct {
	// Name 标识字段
	Name string
	// handler(map[string]func)  依赖于接口
	handler Handler
	// filter
	root func(c *Context)
}

// 路由
func (s *HttpServer) Route(method string, pattern string, handlerfunc func(c *Context)) {
	s.handler.Route(method, pattern, handlerfunc)
}

func (s *HttpServer) Start(address string) error {
	// return http.ListenAndServe(address, nil) -- 因为s增加了serveHTTP而修改
	return http.ListenAndServe(address, s)
}

func (s *HttpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	c := NewContext(w, r)
	s.root(c)
}

// 构造
func NewServer(name string, builder ...FilterBuilder) Server {
	s := NewHandlerBaseOnMap()
	var f Filter = s.ServeHTTP
	// var f Filter = func(c *Context) {
	// 	s.ServeHTTP(c.W, c.R)
	// }

	for i := len(builder) - 1; i >= 0; i-- {
		b := builder[i]
		f = b(f) // builder的参数就是Filter——也就是func(c *context)
	}
	// 等循环结束，一整条链就已经完成——filter1 > filter2 > filter3 > serveHTTP

	return &HttpServer{
		Name:    name,
		handler: s,
		root:    f, // 链条就在这里
	}
}

// ---------------------------------------------------------------------

// -----------------------------增加Context-------------------------------

type Context struct {
	W http.ResponseWriter
	R *http.Request
}

// 封装出来之后，就需要有一个构造方法
func NewContext(w http.ResponseWriter, r *http.Request) *Context {
	return &Context{
		W: w,
		R: r,
	}
}

// 返回对象
type commonResponse struct {
	BizCode int         `json:"biz_code"`
	Msg     string      `json:"msg"`
	Data    interface{} `json:"data"`
}

// 从json中读取信息
func (c *Context) ReadJson(data interface{}) error {
	body, err := io.ReadAll(c.R.Body)
	if nil != err {
		return err
	}
	return json.Unmarshal(body, data)
}

// 返回json
func (c *Context) WriteJson(states int, data interface{}) error {
	bs, err := json.Marshal(data)
	if err != nil {
		return err
	}
	_, err = c.W.Write(bs)
	if nil != err {
		return err
	}
	c.W.WriteHeader(states)
	return nil
}

func (c *Context) OkJson(data interface{}) error {
	return c.WriteJson(http.StatusOK, data)
}

func (c *Context) SystemErrJson(data interface{}) error {
	return c.WriteJson(http.StatusInternalServerError, data)
}

func (c *Context) BadRequestJson(data interface{}) error {
	return c.WriteJson(http.StatusBadRequest, data)
}

// ---------------------------------------------------------------------

// 这个实现不连贯（w,r）
// func SignUp(w http.ResponseWriter, r *http.Request) {
// 	c := NewContext(w, r)
// 	req := signUpReq{}
// 	err := c.ReadJson(req)
// 	if nil != err {
// 		_ = c.BadRequestJson(&commonResponse{
// 			BizCode: 4,
// 			Msg:     "invaild request",
// 		})
// 		return
// 	}
// 	_ = c.OkJson(&commonResponse{
// 		Data: 1234,
// 	})
// }
func SignUp(c *Context) {
	req := signUpReq{}
	err := c.ReadJson(req)
	if nil != err {
		_ = c.BadRequestJson(&commonResponse{
			BizCode: 4,
			Msg:     "invaild request",
		})
		return
	}
	_ = c.OkJson(&commonResponse{
		Data: 1234,
	})
}
